package com.jinsp.skinlib;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;

import java.lang.reflect.Method;

/**
 * Created by luoshuai on 10/27/21
 * <p>
 * 资源管理类，管理当前APP的resource以及插件皮肤的resource
 */
public class ResourceManager {

    protected final String SKIN_FILE_PATH = "skin";
    private Context mContext;
    private Resources mAppResource;     //主APP的资源
    private Resources mSkinResource;    //皮肤包的资源
    private String skinPackageName;     //皮肤包包名

    private ResourceManager() {
    }

    private static class SingletonHolder {
        @SuppressLint("StaticFieldLeak")
        private static final ResourceManager INSTANCE = new ResourceManager();
    }

    public static ResourceManager getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 读取皮肤包资源，反射创建AssetManager
     *
     * @param skinFilePath 皮肤包文件路径
     */
    public void loadSkinResource(String skinFilePath) {
        if (TextUtils.isEmpty(skinFilePath)) {
            reset();
        } else {
            PackageManager packageManager = mContext.getPackageManager();
            //获取皮肤包应用包名
            PackageInfo packageArchiveInfo = packageManager.getPackageArchiveInfo(skinFilePath,
                    PackageManager.GET_ACTIVITIES);
            if (packageArchiveInfo == null) {
                reset();
                return;
            }
            this.skinPackageName = packageArchiveInfo.packageName;
            //反射创建AssetManager
            AssetManager assetManager = null;
            try {
                assetManager = AssetManager.class.getDeclaredConstructor().newInstance();
                @SuppressLint("DiscouragedPrivateApi")
                Method targetMethod = AssetManager.class.getDeclaredMethod("addAssetPath", String.class);
                if (targetMethod == null) {
                    return;
                }
                targetMethod.setAccessible(true);
                //通过AssetManager解析皮肤包资源
                targetMethod.invoke(assetManager, skinFilePath);
            } catch (Exception e) {
                e.printStackTrace();
            }
            mSkinResource = new Resources(assetManager, mAppResource.getDisplayMetrics(),
                    mAppResource.getConfiguration());
            //保存皮肤包路径
            SharedPreferencesUtils.saveStringValue(SKIN_FILE_PATH, skinFilePath);
        }
    }

    /**
     * 初始化主APP资源
     *
     * @param context 上下文，application对象
     */
    public void init(Context context) {
        mContext = context.getApplicationContext();
        mAppResource = mContext.getResources();
    }

    /**
     * 更换文字（不要使用）
     *
     * @param appStringResId 主APP文字
     * @return 插件或主APP中文本
     */
    public String getStringId(int appStringResId) {
        int stringId = findSkinResourceId(appStringResId);
        if (stringId == 0) {
            return mAppResource.getString(appStringResId);
        }
        return mSkinResource.getString(stringId);
    }

    /**
     * 更换文字字体
     *
     * @param appFontResId 主APP字体
     * @return 插件或者主APP中字体
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public Typeface getFont(int appFontResId) {
        int fontId = findSkinResourceId(appFontResId);
        if (fontId == 0) {
            return mAppResource.getFont(appFontResId);
        }
        return mSkinResource.getFont(fontId);
    }

    /**
     * 获取文本颜色值
     *
     * @param appColorStateListResId 主APP文本颜色id号
     * @return 插件或者主APP文本颜色
     */
    public ColorStateList getColorStateList(int appColorStateListResId) {
        int colorStateListId = findSkinResourceId(appColorStateListResId);
        if (colorStateListId == 0) {
            return mAppResource.getColorStateList(appColorStateListResId);
        }
        return mSkinResource.getColorStateList(colorStateListId);
    }

    /**
     * 获取颜色id值
     *
     * @param appColorResId 主APP颜色id
     * @return 插件或者主APP中颜色值
     */
    public int getColor(int appColorResId) {
        int colorId = findSkinResourceId(appColorResId);
        if (colorId == 0) {
            return mAppResource.getColor(appColorResId);
        }
        return mSkinResource.getColor(colorId);
    }

    /**
     * 获取对应图片资源
     *
     * @param appDrawableResId 主APP图片id
     * @return 插件或者主APP中的图片drawable
     */
    public Drawable getDrawable(int appDrawableResId) {
        int drawableId = findSkinResourceId(appDrawableResId);
        if (drawableId == 0) {
            return mAppResource.getDrawable(appDrawableResId);
        }
        return mSkinResource.getDrawable(drawableId);
    }

    /**
     * 获取背景色值
     *
     * @param appBackgroundResId 主APP背景色id，可能是color or drawable
     * @return 对应的color值或者drawable资源
     */
    public Object getBackground(int appBackgroundResId) {
        String resourceTypeName = mAppResource.getResourceTypeName(appBackgroundResId);
        if ("color".equals(resourceTypeName)) {
            return getColor(appBackgroundResId);
        } else {
            return getDrawable(appBackgroundResId);
        }
    }

    /**
     * 根据主APP内资源id号查询插件包内对应的资源id号
     *
     * @param appResId 主APPid号
     * @return 插件包内对应资源id号
     */
    private int findSkinResourceId(int appResId) {
        if (mSkinResource == null || TextUtils.isEmpty(skinPackageName)) {
            return 0;
        }
        //主APP内资源入口名称 例如：R.color.colorPrimary 返回 colorPrimary
        String resourceEntryName = mAppResource.getResourceEntryName(appResId);
        //主APP内资源类型名称 例如：R.color.colorPrimary 返回 color
        String resourceTypeName = mAppResource.getResourceTypeName(appResId);
        //寻找插件包中的资源
        return mSkinResource.getIdentifier(resourceEntryName, resourceTypeName, skinPackageName);
    }

    /**
     * 获取系统主题中资源id号，例如xml中使用了 ?xxx
     *
     * @param context 上下文实例
     * @param attrs   属性列表
     * @return 系统主题中的id列表
     */
    public int[] getThemeResId(Context context, int... attrs) {
        int[] resId = new int[attrs.length];
        TypedArray a = context.getApplicationContext().obtainStyledAttributes(attrs);
        for (int i = 0; i < attrs.length; i++) {
            resId[i] = a.getResourceId(i, 0);
        }
        a.recycle();
        return resId;
    }

    /**
     * 重置资源值，从皮肤包切换为主APP资源
     */
    public void reset() {
        skinPackageName = null;
        mSkinResource = null;
        //清楚皮肤包路径
        SharedPreferencesUtils.saveStringValue(SKIN_FILE_PATH, null);
    }
}
